home *** CD-ROM | disk | FTP | other *** search
/ PC-Blue - MS DOS Public Domain Library / PC-Blue MS-DOS Public Domain Library - NYACC.iso / vol309 / jdutil.arc / MV.ASM < prev    next >
Encoding:
Assembly Source File  |  1986-08-14  |  39.6 KB  |  952 lines

  1.         TITLE MV - MSDOS FILE MOVE UTILITY
  2.         PAGE 55,132
  3. ;***************************************************************************
  4. ;       THIS PROGRAM RENAMES A FILE OR DIRECTORY, OR MOVES ONE OR MORE FILES
  5. ;       OR DIRECTORIES BETWEEN DISKS OR DIRECTORIES.
  6. ;
  7. ;       USAGE (afn = ambiguous file name, ufn = unambiguous file name,
  8. ;              dir = directory):
  9. ;
  10. ;               MV ufn1 ufn2    - renames or moves ufn1 to ufn2.
  11. ;
  12. ;               MV afn1 afn2 ... dir  - moves one or more files into dir.
  13. ;
  14. ;               MV -R dir1 dir2  if dir2 doesn't exist, renames or moves
  15. ;                                 dir1 to dir2.
  16. ;                                 (note: DOS 2 requires that renaming a direc-
  17. ;                                 tory be done by creating dir2, moving all
  18. ;                                 files from dir1 into it, then deleting dir1).
  19. ;
  20. ;                               - if dir2 exists, makes dir1 a subdirectory
  21. ;                                 of it.
  22. ;
  23. ;       SWITCHES (OPTIONAL):
  24. ;
  25. ;        I  prompts before overwriting files
  26. ;
  27. ;        R  allows recursively moving directories.
  28. ;
  29. ;               V  turns on "verbose" mode (shows name of each file as it
  30. ;                      is moved).
  31. ;***************************************************************************
  32. ;   TO BUILD MV.EXE:
  33. ;    MASM MV,MV,NUL,NUL
  34. ;    LINK MV,MV,NUL,ASM -C3100
  35. ;***************************************************************************
  36. ;    BY: JON DART
  37. ;        DEPARTMENT OF ANTHROPOLOGY
  38. ;        UCSD C-001
  39. ;        LA JOLLA, CA 92093
  40. ;***************************************************************************
  41. ;    VERSION 2.1, 06-JUL-86 (CHANGES TO MEMORY ALLOC, ALLOWS HYPHEN FOR
  42. ;                SWITCHES, NOW ASSEMBLES UNDER MASM 4.0)
  43. ;    VERSION 2.0, 30-JUN-86 (MINOR CLEANING UP, R AND I SWITCHES ADDED, C
  44. ;                SWITCH REMOVED)
  45. ;       VERSION 1.9, 26-APR-86 (DOESN'T EXIT AFTER USER RESPONDS N TO 
  46. ;                    OVERWRITE MSG.)
  47. ;       VERSION 1.8, 31-MAR-86 (MORE BUG FIXES (*SIGH*))
  48. ;       VERSION 1.7, 29-MAR-86 (BUG FIXES)
  49. ;       VERSION 1.6, 24-MAR-86 (ALLOWS MULTIPLE SOURCE FILES)
  50. ;       VERSION 1.5, 25-JAN-86 (ADDS CHECK FOR IDENTICAL SOURCE & DEST)
  51. ;       VERSION 1.4, 14-JAN-86 (ADDS SWITCHES)
  52. ;       VERSION 1.3, 12-JAN-86 (ADDS RECURSION)
  53. ;       VERSION 1.2, 01-JAN-86
  54. ;       VERSION 1.1, 01-NOV-85
  55. ;       VERSION 1.0, 29-SEP-85
  56. ;***************************************************************************
  57.  
  58. PATHSIZE EQU    65                      ;MAX. SIZE OF DOS PATHNAME, +1
  59. BUFSIZE EQU     32*1024                 ;SIZE OF COPY BUFFER
  60. MAXLEVEL EQU    12                      ;MAX NESTING LEVEL FOR DIRECTORIES
  61. MAXARGS EQU     40                      ;MAXIMUM # OF COMMAND LINE ARGUMENTS
  62. PRGSIZE EQU     1800H                   ;MAX. SIZE OF CODE AND FIXED DATA
  63. TRUE    EQU     1
  64. FALSE   EQU     0
  65. CONFIRM EQU     FALSE                   ;"CONFIRM BEFORE OVERWRITE" OPTION (DEFAULT VALUE)
  66. RECURSE EQU    FALSE            ;"RECURSE" OPTION (DEFAULT VALUE)
  67. VERBOSE EQU     FALSE                   ;"VERBOSE" OPTION (DEFAULT VALUE)
  68. M       EQU     BYTE PTR 0[BX]
  69. BIT$DIR EQU     00010000B               ;BIT IN ATTRIBUTE FOR DIRECTORY
  70. BIT$RO  EQU     00000001B               ;BIT IN ATTRIBUTE FOR WRITE-PROTECT
  71.  
  72.         .XLIST
  73.         INCLUDE ASCII.DEF
  74.         INCLUDE MSDOS2.DEF
  75.     INCLUDE MACROS.DEF
  76.         .LIST
  77.  
  78. MVINFO  STRUC
  79. NEWDIR  DW      1 DUP (?)               ;FLAG, =1 IF NEW DIRECTORY CREATED
  80. SRCTYPE DB     2 DUP (?)                ;TYPE OF SOURCE (0 IF UFN)
  81. DESTTYPE DB    2 DUP (?)                ;TYPE OF DEST (0 IF UFN)
  82. ARG1    DB      PATHSIZE DUP (?)        ;FIRST ARGUMENT (SOURCE)
  83. ARG2    DB      PATHSIZE DUP (?)        ;SECOND ARGUMENT (DEST)
  84. ARG2A   DB      PATHSIZE DUP (?)        ;SOURCE PREFIX + DEST
  85. SSPATH  DB      PATHSIZE DUP (?)        ;SOURCE SEARCH PATH
  86. SPREFIX DB      PATHSIZE DUP (?)        ;SOURCE LEAD-IN PATH
  87. DSPATH  DB      PATHSIZE DUP (?)        ;DEST SEARCH PATH
  88.                                         ;(USED ONLY AS SCRATCH AREA)
  89. DPREFIX DB      PATHSIZE DUP (?)        ;DEST LEAD-IN PATH
  90. SRCNAME DB      PATHSIZE DUP (?)        ;UNAMBIGUOUS SOURCE NAME
  91. DESTNAME DB     PATHSIZE DUP (?)        ;UNAMBIG. DEST NAME
  92. DTA     DB      128 DUP (?)             ;DTA FOR SEARCH FN.
  93. MVINFO  ENDS
  94. MVSTRUCSIZE EQU 9*PATHSIZE+135          ;SIZE OF STRUCTURE
  95.  
  96. DGROUP  GROUP DATA,STACK
  97. DATA    SEGMENT WORD PUBLIC
  98. ;       GLOBAL MEMORY DEFINITIONS:
  99. ;
  100. MSG1    DB 'MV Version 2.1 by Jon Dart (06-Jul-86)',CR,LF,CR,LF
  101.         DB 'USAGE (afn = ambiguous file name, ufn = unambiguous file name,'
  102.         DB CR,LF
  103.         DB '       dir = directory):',CR,LF,CR,LF
  104.         DB 'MV ufn1 ufn2          move or rename ufn1 to ufn2.',CR,LF,CR,LF
  105.         DB 'MV afn1 afn2 ... dir  move one or more files into dir.',CR,LF,CR,LF
  106.         DB "MV -R dir1 dir2       if dir2 doesn't exist, move or rename"
  107.         DB CR,LF
  108.         DB '                      dir1 to dir2.',CR,LF,CR,LF
  109.         DB '                      if dir2 exists, make dir1 a subdirectory'
  110.         DB CR,LF
  111.         DB '                      of it.',CR,LF,CR,LF
  112.         DB 'SWITCHES (OPTIONAL):',CR,LF,CR,LF
  113.         DB '-I   prompt before overwriting files.',CR,LF,CR,LF
  114.     DB '-R   allow recursive moving of directories.',CR,LF,CR,LF
  115.         DB '-V   echo file names as they are moved.',CR,LF
  116.         DB 0
  117. MSG2    DB      ': file not found.',CR,LF,0
  118. MSG3    DB      'Source and dest are incompatible.',CR,LF,0
  119. MSG4    DB      ' exists. Overwrite [Y or N]? ',0
  120. MSG5    DB      ': open failed.',CR,LF,0
  121. MSG6    DB      ': file is R/O. Are you SURE [Y or N]? ',0
  122. MSG7    DB    ': directory.',CR,LF,0
  123. MSG8    DB      ': write error.',CR,LF,0
  124. MSG9    DB      '; read error.',CR,LF,0
  125. MSG10   DB      ': write error (probably disk full).',CR,LF,0
  126. MSG11   DB      ': rename failed.',CR,LF,0
  127. MSG12   DB      ": can't create.",CR,LF,0
  128. MSG13   DB      ": can't remove.",CR,LF,0
  129. MSG14   DB      "Directories nested too deep.",CR,LF,0
  130. MSG15   DB      "Insufficient memory for buffers.",CR,LF,0
  131. MSG16   DB      ": Illegal switch.",CR,LF,0
  132. MSG17   DB      "Error: source and dest are identical.",CR,LF,0
  133. MSG18   DB      "Too many arguments.",CR,LF,0
  134. DATA    ENDS
  135.  
  136. STACK   SEGMENT PARA STACK
  137.         DB      512 DUP (?)
  138. STACK   ENDS
  139.  
  140. ;       VARIABLES AND BUFFER AREAS, STORED IN FREE MEMORY ABOVE PROGRAM,
  141. ;       RELATIVE TO "BASE" (DS AND ES WILL NORMALLY POINT TO START OF THIS AREA):
  142.  
  143. RBASE   EQU     2                       ;POINTER TO MVSTRUC IN RSTACK
  144. LEVEL   EQU     4                       ;RECURSION LEVEL
  145. SRCDRIVE  EQU   6                       ;SOURCE DRIVE (0 = DEFAULT)
  146. DESTDRIVE  EQU  8                       ;DEST DRIVE (0 = DEFAULT)
  147. INHANDLE EQU    10                      ;INPUT FILE HANDLE
  148. OUTHANDLE EQU   12                      ;OUTPUT FILE HANDLE
  149. IFLAG   EQU     14                      ;CONFIRM FLAG
  150. RFLAG    EQU    16            ;RECURSE FLAG
  151. VFLAG   EQU     18                      ;VERBOSE FLAG
  152. CMDTAIL EQU     20                      ;STORAGE FOR COMMAND TAIL
  153. DEST_DTA EQU    CMDTAIL+128             ;HOLDS INFO ON DEST, RETURNED FROM DOS
  154.                                         ;FN 4E.
  155. NUMARGS EQU     DEST_DTA+128            ;NUMBER OF ARGUMENTS ON COMMAND LINE
  156. ARGPTRS EQU     NUMARGS+2               ;POINTERS TO START OF ARGUMENTS
  157. BUFFER  EQU     ARGPTRS+(2*MAXARGS)     ;FILE XFER BUFFER
  158. RSTACK  EQU     BUFFER+BUFSIZE          ;RECURSION STACK
  159. DATASIZE EQU    (RSTACK)+(MAXLEVEL*MVSTRUCSIZE)+256
  160.  
  161.         PAGE +
  162. CODE    SEGMENT BYTE PUBLIC
  163. ASSUME CS:CODE,DS:DGROUP,ES:DGROUP,SS:STACK
  164. EXTRN   CPYCNT:NEAR,UC:NEAR,UCSTR:NEAR,CRLF:NEAR,ERRORMSG:NEAR,COUT:NEAR
  165. EXTRN   CIN:NEAR,CLRCO:NEAR,SKIPSP:NEAR,TYPTX:NEAR,ERRORMSG:NEAR,CLRCO:NEAR
  166. EXTRN   FIXPATH:NEAR,GETYORN:NEAR,UNLINK2:NEAR
  167. EXTRN   TYPE_DIR:ABS,TYPE_AFN:ABS,TYPE_UFN:ABS,TYPE_DSP:ABS,TYPE_DRV:ABS
  168. EXTRN   TYPE_UNK:ABS
  169.  
  170. ;*********************
  171. ;* MACRO DEFINITIONS *
  172. ;*********************
  173.  
  174. ADDR    MACRO   REG,OFFST               ;COMPUTE ADDRESS OFFSET FROM BASE REGISTER (BX)
  175.         MOV     REG,BX
  176.         ADD     REG,OFFSET OFFST
  177.         ENDM
  178.  
  179. ERROR   MACRO   ERRNUM                  ;SHOW ERROR MESSAGE
  180.         MOV     DX,OFFSET DGROUP:MSG&ERRNUM
  181.     CALL    PRTERR
  182.         ENDM
  183.  
  184. ;**********************
  185. ; PROGRAM ENTRY POINT *
  186. ;**********************
  187. ENTRY:
  188.         TEST_DOS2                       ;TEST FOR DOS 2.0, EXIT IF DOS 1
  189.     MOV    AX,DS
  190.     MOV    ES,AX
  191.     MOV    BX,((PRGSIZE+DATASIZE) SHR 4)+1 ;RESERVE SPACE FOR PROGRAM+BUFFERS
  192.     MOV    AH,SET_BLOCK
  193.     INT    DOS
  194.     JB    MEMERR            ;IF ERROR
  195.     MOV    AX,DS            ;GET DATA SEG
  196.     ADD    AX,PRGSIZE SHR 4    ;ADD OFFSET TO BUFFER AREA
  197.     MOV    ES,AX            ;SET EXTRA SEG TO POINT TO BUFFERS
  198.     JMP    SHORT MEMOK
  199. MEMERR: ERROR   15
  200.         JMP     EXIT2
  201. MEMOK:
  202.         MOV     BX,OFFSET (80H)          ;POINT TO BYTE COUNT FOR COMMAND LINE
  203.         CMP     [BX],BYTE PTR 0
  204.         JE      USEMSG                  ;IF NO COMMAND TAIL
  205.         PUSH    BX
  206.         MOV     DL,[BX]
  207.         MOV     DH,0
  208.         ADD     BX,DX
  209.         INC     BX
  210.         MOV     [BX],BYTE PTR 0         ;PUT 0 BYTE AT END OF COMMAND LINE
  211.         POP     BX
  212.         INC     BX
  213.         CALL    UCSTR                   ;CONVERT COMMAND LINE TO UPPER CASE
  214.         CALL    SKIPSP                  ;SKIP LEADING SPACES
  215.         JNC     L_2                     ;IF SOMETHING ON LINE
  216. USEMSG: ERROR   1
  217.         JMP     EXIT2
  218. L_2:
  219.         MOV     SI,BX
  220.         MOV     DI,OFFSET CMDTAIL
  221.         MOV     CX,128
  222.         CALL    CPYCNT                  ;SAVE COMMAND TAIL
  223.         MOV     AX,ES
  224.         MOV     DS,AX                   ;SET DATA SEG TO VARIABLE AREA
  225.         MOV     BYTE PTR DS:IFLAG,CONFIRM  ;SET CONFIRM FLAG DEFAULT
  226.         MOV     BYTE PTR DS:VFLAG,VERBOSE  ;SET VERBOSE FLAG DEFAULT
  227.     MOV    BYTE PTR DS:RFLAG,FALSE    ;SET RECURSIVE FLAG DEFAULT
  228.     MOV    WORD PTR DS:LEVEL,0    ;SET RECURSION LEVEL = 0
  229.         MOV     BYTE PTR DS:SRCDRIVE,0  ;SET SOURCE DRIVE DEFAULT
  230.         MOV     BYTE PTR DS:DESTDRIVE,0 ;SET DEST DRIVE DEFAULT
  231. ;***************************
  232. ; COLLECT SWITCHES, IF ANY *
  233. ;***************************
  234.         MOV     BX,OFFSET CMDTAIL       ;POINT TO COMMAND TAIL
  235. NEXTSW:
  236.         CALL    SKIPSP
  237.         JB      USEMSG                  ;IF NOTHING ON LINE BESIDES SWITCHES
  238.         CMP     BYTE PTR [BX],'/'       ;SWITCH SPECIFIED?
  239.         JE    GOTSW            ;YES
  240.     CMP    BYTE PTR [BX],'-'    ;CHECK FOR HYPHEN, TOO
  241.     JNE    NOSWITCH
  242. GOTSW:
  243.         INC     BX                      ;SKIP OVER SWITCH CHARACTER
  244.         CALL    SKIPSP                  ;SKIP LEADING BLANKS
  245.         JB      USEMSG                  ;IF NOTHING
  246.         CALL    UC                      ;MAKE SWITCH UPPER CASE
  247.         CMP     AL,'V'                  ;VERBOSE SWITCH?
  248.         JE      VSWITCH
  249.         CMP     AL,'I'                  ;INTERACTIVE SWITCH?
  250.         JE      ISWITCH
  251.     CMP    AL,'R'            ;RECURSIVE SWITCH?
  252.     JE    RSWITCH
  253.         CALL    COUT                    ;DISPLAY BAD CHAR.
  254.         ERROR   16                      ;ILLEGAL SWITCH
  255.         JMP     EXIT2
  256. VSWITCH:
  257.         MOV     AL,1
  258.         SUB     AL,BYTE PTR DS:VFLAG
  259.         MOV     BYTE PTR DS:VFLAG,AL    ;TOGGLE VFLAG
  260.         INC     BX                      ;SKIP SWITCH LETTER
  261.         JMP     NEXTSW
  262. ISWITCH:
  263.         MOV     AL,1
  264.         SUB     AL,BYTE PTR DS:IFLAG
  265.         MOV     BYTE PTR DS:IFLAG,AL    ;TOGGLE IFLAG
  266.         INC     BX                      ;SKIP SWITCH LETTER
  267.         JMP     NEXTSW
  268. RSWITCH:
  269.         MOV     AL,1
  270.         SUB     AL,BYTE PTR DS:RFLAG
  271.         MOV     BYTE PTR DS:RFLAG,AL    ;TOGGLE RFLAG
  272.         INC     BX                      ;SKIP SWITCH LETTER
  273.         JMP     NEXTSW
  274. ;************************************************************
  275. ; SCAN THE COMMAND LINE AND STORE POINTERS TO ALL ARGUMENTS *
  276. ;************************************************************
  277. NOSWITCH:
  278.         MOV     CX,0                    ;CX COUNTS # OF ARGUMENTS
  279.         MOV     SI,OFFSET DS:ARGPTRS    ;POINT TO ARG POINTER TABLE
  280. SAVEARG:
  281.         INC     CX                      ;BUMP ARGUMENT COUNT
  282.         CMP     CX,MAXARGS
  283.         JG      TOOMANY                 ;IF TOO MANY
  284.         MOV     DS:[SI],BX              ;SAVE POINTER TO ARG
  285.         ADD     SI,2                    ;ADVANCE TO NEXT TABLE ENTRY
  286. CNTARGS:
  287.         MOV     AL,DS:[BX]              ;GET CHAR. FROM COMMAND LINE
  288.         CMP     AL,0
  289.         JE      ENDLINE                 ;IF END OF LINE
  290.         COMPLIST <SPACE,TAB>,NEXTARG    ;SEE IF SPACE OR TAB
  291.         INC     BX
  292.         JMP     CNTARGS                 ;LOOP TILL DELIMITER FOUND
  293. NEXTARG:
  294.         CALL    SKIPSP                  ;SKIP SPACES AND TABS
  295.         JNB     SAVEARG                 ;IF NOT EOL, BACK TO TOP OF LOOP
  296. ENDLINE:
  297.         CMP     CX,0                    ;CHECK ARGUMENT COUNT
  298.         JE      NOARGS                  ;IF NO ARGS
  299.         CMP     CX,1
  300.         JG      ARGSOK                  ;IF >=2 ARGS
  301.         MOV     DS:[SI],BX              ;EXACTLY ONE ARGUMENT, SO
  302.         INC     CX                      ;MAKE A DUMMY (NULL) 2ND ARGUMENT
  303.         JMP     SHORT ARGSOK
  304. NOARGS:
  305.         JMP     USEMSG                  ;ELSE USE MESSAGE
  306. TOOMANY:
  307.         ERROR   18                      ;TOO MANY ARGUMENTS (PRETTY UNLIKELY)
  308.         JMP     EXIT2
  309. ;************************************
  310. ;* COLLECT THE DESTINATION PATHNAME *
  311. ;************************************
  312. ARGSOK: MOV     WORD PTR DS:NUMARGS,CX  ;SAVE NUMBER OF ARGUMENTS
  313.         DEC     CX                      ;NUMBER OF ARGS - 1
  314.         ADD     CX,CX                   ;TIMES TWO
  315.         MOV     SI,OFFSET DS:ARGPTRS
  316.         ADD     SI,CX                   ;POINT TO ADDR. OF LAST ARGUMENT (DEST)
  317.         MOV     BX,DS:[SI]              ;PUT ADDR. INTO BX
  318.         MOV     DI,OFFSET RSTACK+ARG2   ;POINT TO STORAGE FOR DEST
  319.         MOV     AL,[BX+1]
  320.         CMP     AL,':'                  ;CHECK FOR DEST DRIVE SPEC
  321.         JNE     GETLAST                 ;IF NONE
  322.         MOV     AL,[BX]                 ;DRIVE SPECIFIED, GET DRIVE LETTER
  323.         SUB     AL,'A'-1                ;MAKE BINARY
  324.         MOV     BYTE PTR DS:DESTDRIVE,AL   ;SAVE DRIVE
  325. GETLAST: MOV    AL,[BX]                 ;GET A CHAR. FROM CMD LINE
  326.         COMPLIST <0,SPACE,TAB>,ENDARG2  ;IF DELIMITER
  327.         STOSB                           ;NOT DELIMITER, STORE IT
  328.         INC     BX                      ;BUMP POINTER
  329.         JMP     GETLAST                 ;LOOP
  330. ENDARG2:
  331.         MOV     AL,0
  332.         STOSB                           ;END DEST W. 0
  333. ;***********************************************************
  334. ;* LOOP, TAKING ONE SOURCE AT A TIME AND MOVING IT TO DEST *
  335. ;***********************************************************
  336.         MOV     CX,WORD PTR DS:NUMARGS  ;GET NUMBER OF ARGS AGAIN
  337.         DEC     CX                      ;-1
  338.         MOV     SI,OFFSET DS:ARGPTRS    ;POINT TO POINTER TABLE
  339. MOVE1ARG:
  340.         MOV     BX,DS:[SI]              ;GET POINTER TO ARG
  341.         PUSH    SI
  342.         PUSH    CX
  343.         CALL    MOVEARG                 ;MOVE IT
  344.         POP     CX
  345.         POP     SI
  346.         ADD     SI,2                    ;ADVANCE TO NEXT ARG POINTER
  347.         LOOP    MOVE1ARG                ;LOOP TILL NO MORE ARGS TO MOVE
  348.         JMP     EXIT2
  349.  
  350. ;**********************************
  351. ;* MOVE 1 SOURCE ARGUMENT TO DEST *
  352. ;**********************************
  353. MOVEARG PROC   NEAR
  354.         MOV     BYTE PTR DS:SRCDRIVE,0  ;SET SOURCE DRIVE DEFAULT
  355.         MOV     DI,OFFSET RSTACK+ARG1   ;COLLECT SOURCE
  356.         MOV     AL,[BX+1]
  357.         CMP     AL,':'                  ;CHECK FOR SOURCE DRIVE SPEC
  358.         JNE     GETARG
  359.         MOV     AL,[BX]                 ;GET DRIVE LETTER
  360.         SUB     AL,'A'-1                ;MAKE BINARY
  361.         MOV     BYTE PTR DS:SRCDRIVE,AL ;SAVE SOURCE DRIVE
  362. GETARG: MOV     AL,[BX]                 ;COPY FROM [BX] TO [DI] UNTIL DELIMITER
  363.         COMPLIST <0,SPACE,TAB>,ENDARG
  364.         STOSB
  365.         INC     BX
  366.         JMP     GETARG
  367. ENDARG: MOV     AL,0
  368.         STOSB                           ;END ARG1 W. ZERO
  369.         MOV     WORD PTR DS:RBASE,RSTACK   ;SAVE OFFSET TO RSTACK
  370.         CALL    MOVEIT                  ;DO THE STUFF
  371.         RET
  372. MOVEARG ENDP
  373.  
  374.         PAGE +
  375. ;********************************************************************
  376. ; THIS IS THE MOVE SUBROUTINE. IT ASSUMES THAT ARG1 AND ARG2 ARE
  377. ; SET UP PROPERLY IN THE RECURSION STACK AREA, AND THAT "RBASE" POINTS
  378. ; TO THE START OF THE DATA STRUCTURE FOR THIS RECURSION LEVEL.
  379. ;
  380. MOVEIT  PROC    NEAR
  381.         MOV     BX,WORD PTR DS:RBASE    ;GET BASE ADDR. (POINTER TO MVINFO)
  382.         CALL    SETUP                   ;PARSE ARGUMENTS, CHECK FOR ERRORS
  383.         JNC     NOARGERR                ;IF OK
  384.         JMP     EXIT2                   ;QUIT IF ERROR
  385. ;******************************************
  386. ; SEE IF ANYTHING MATCHES THE SOURCE SPEC *
  387. ;******************************************
  388. NOARGERR:
  389.         ADDR    DX,SSPATH               ;POINT TO SEARCH PATH
  390.         MOV     CX,31H                  ;SET SEARCH ATTRIBUTES
  391.         MOV     AH,FIND_FIRST
  392.         INT     DOS                     ;SEARCH FOR 1ST MATCH
  393.         JNC     SRCOK                   ;OK IF SOMETHING FOUND
  394.         ADDR    DX,ARG1
  395.         CALL    ERRORMSG                ;ELSE SHOW ARGUMENT
  396.         ERROR   2                       ;SAY IT DOESN'T EXIST
  397.         JMP     EXIT2
  398. ;**************************************
  399. ; CREATE DEST DIRECTORY, IF NECESSARY *
  400. ;**************************************
  401. SRCOK:  CMP     WORD PTR [BX].NEWDIR,1  ;CHECK NEW DIRECTORY FLAG
  402.         JNE     GOTONE                  ;IF NOT SET
  403.         ADDR    DX,ARG2A                ;POINT TO DEST NAME
  404.         MOV     AH,MKDIR
  405.         INT     DOS                     ;CREATE NEW DIRECTORY
  406.         JNB     GOTONE                  ;IF OK
  407.         ADDR    DX,ARG2A                ;IF CAN'T CREATE,
  408.         CALL    ERRORMSG                ;SHOW DIRECTORY NAME
  409.         ERROR   12                      ;AND ERROR MSG.
  410.         JMP     EXIT2                   ;EXIT 2 DOS
  411. ;**************
  412. ; TOP OF LOOP *
  413. ;**************
  414. GOTONE:
  415.         CALL    BUILD_NAMES             ;MAKE UNAMBIG. SOURCE AND DEST NAMES
  416.         JNC     NOSKIP
  417.         JMP     NEXTFILE                ;IF SOURCE IS "." OR ".." OR = DEST
  418. NOSKIP:
  419.         CMP     BYTE PTR DS:VFLAG,TRUE  ;CHECK VERBOSE FLAG
  420.         JNE     QUIET                   ;IF QUIET MODE
  421.         ADDR    DX,SRCNAME              ;NOT QUIET, SHOW VERBIAGE
  422.         CALL    ERRORMSG
  423.         CALL    TYPTX
  424.         DB      ' -->',SPACE+200Q
  425.         ADDR    DX,DESTNAME
  426.         CALL    ERRORMSG
  427.         CALL    CRLF
  428. QUIET:
  429.         TEST    [BX].DTA+21,BIT$DIR     ;IS SOURCE A DIRECTORY?
  430.         JZ      CHKDRIVES               ;NO
  431. ;***********************************************
  432. ; IF SOURCE IS A DIRECTORY, RECURSIVELY MOVE IT*
  433. ;***********************************************
  434.     CMP    BYTE PTR DS:RFLAG,TRUE    ;R FLAG SET?
  435.     JNE    NEXTFILE        ;NO, SKIP OVER DIRECTORY
  436.         CMP     WORD PTR DS:LEVEL,MAXLEVEL-1 ;ARE WE AT MAX LEVEL?
  437.         JL      NOTMAX                  ;NO
  438.         ERROR   14                      ;YES, TOO DEEP
  439.         JMP     EXIT2
  440. NOTMAX:
  441.         COPYPATH SRCNAME,(ARG1+MVSTRUCSIZE)  ;COPY SOURCE DIRECTORY TO ARG1 AT NEXT LEVEL
  442.         COPYPATH DESTNAME,(ARG2+MVSTRUCSIZE) ;COPY DEST NAME TO ARG2 AT NEXT LEVEL
  443.         PUSH    BX                      ;SAVE POINTER TO BASE
  444.         INC     WORD PTR DS:LEVEL       ;INCREMENT RECURSION LEVEL
  445.         ADD     WORD PTR DS:RBASE,MVSTRUCSIZE ;ADVANCE BASE POINTER
  446.         CALL    MOVEIT                  ;MOVE THE DIRECTORY
  447.         POP     BX                      ;RESTORE BASE POINTER
  448.         DEC     WORD PTR DS:LEVEL       ;DECREMENT RECURSION LEVEL
  449.         SUB     WORD PTR DS:RBASE,MVSTRUCSIZE  ;RESTORE BASE TO PREVIOUS LEVEL
  450.         ADDR    DX,DTA
  451.         MOV     AH,SET_DTA
  452.         INT     DOS                     ;RESET DTA
  453.         JMP     SHORT NEXTFILE          ;DO NEXT FILE
  454. ;*****************************************
  455. ; IF SOURCE IS A FILE, COPY OR RENAME IT *
  456. ;*****************************************
  457. CHKDRIVES:
  458.         MOV     AL,BYTE PTR DS:SRCDRIVE    ;GET SOURCE DRIVE
  459.         CMP     AL,BYTE PTR DS:DESTDRIVE   ;COMPARE W. DEST..
  460.         JNE     MOVEM
  461.         CALL    RENAME_FILE             ;SAME DRIVE, JUST RENAME
  462.         JMP     SHORT NEXTFILE
  463. MOVEM:  CALL    COPY_FILE               ;DIFFERENT DRIVE, COPY SOURCE TO DEST
  464. ;*****************
  465. ; BOTTOM OF LOOP *
  466. ;*****************
  467. NEXTFILE:
  468.         MOV     AH,FIND_NEXT
  469.         INT     DOS                     ;FIND NEXT MATCH, IF ANY
  470.         JC      NOMORE                  ;IF NONE
  471.         JMP     GOTONE                  ;GOT ONE, BACK TO TOP OF LOOP
  472. ;**********************
  473. ; NO MORE FILES, DONE *
  474. ; *********************
  475. NOMORE: MOV     AX,WORD PTR [BX].SRCTYPE    ;GET TYPE OF SOURCE
  476.         CMP     AX,TYPE_DIR             ;DIRECTORY?
  477.         JNE     JUSTCLOSE               ;NO
  478.         ADDR    DX,ARG1                 ;YES, POINT TO NAME
  479.         MOV     AH,RMDIR
  480.         INT     DOS                     ;REMOVE IT
  481.         JNB     JUSTCLOSE
  482.         ADDR    DX,ARG1
  483.         CALL    ERRORMSG
  484.         ERROR   13                      ;COMPLAIN IF ERROR
  485.         JMP     CLOSE2
  486. ;**************
  487. ; NORMAL EXIT *
  488. ;**************
  489. JUSTCLOSE:
  490.         MOV     BX,WORD PTR DS:OUTHANDLE
  491.         MOV     AH,DOS2_CLOSE
  492.         INT     DOS                     ;CLOSE OUTPUT FILE
  493.         MOV     BX,WORD PTR DS:INHANDLE
  494.         MOV     AH,DOS2_CLOSE
  495.         INT     DOS                     ;CLOSE INPUT FILE
  496.         RET                             ;ALL DONE
  497. MOVEIT  ENDP
  498.  
  499.         PAGE +
  500. ;*************************************************************************
  501. ; THIS PROCEDURE PARSES ARG1 AND ARG2 AND CHECKS FOR INCOMPATIBLE TYPES
  502. ; (E.G. "MV FOOBAR *.*").  IF SUCCESSFUL, IT SETS SSPATH = SOURCE SEARCH
  503. ; PATH, SPREFIX = SOURCE PREFIX, DSPATH = DEST SEARCH PATH (NOT USED),
  504. ; DPREFIX = DEST PREFIX, SRCTYPE = SOURCE TYPE DESTTYPE = DESTINATION TYPE.
  505. ; IT ALSO SETS "NEWDIR"=1 IF THE DESTINATION DIRECTORY MUST BE CREATED.
  506. ; ALL OF THESE VARIABLES ARE IN A STRUCTURE OF TYPE 'MVINFO' IN THE RECURSION
  507. ; STACK AREA (STARTING AT THE ADDRESS IN 'RBASE').
  508. ;
  509. ; ON RETURN, THE CARRY FLAG IS SET IF AN ERROR OCCURRED.
  510. ;
  511. SETUP   PROC    NEAR
  512.         MOV     BX,WORD PTR DS:RBASE    ;GET ADDR. OF DATA STRUCTURE
  513.         MOV     WORD PTR [BX].NEWDIR,0  ;CLEAR "NEW DIRECTORY" FLAG
  514.         ADDR    DX,DTA
  515.         MOV     AH,SET_DTA
  516.         INT     DOS                     ;SET DTA
  517.         ADDR    SI,ARG1
  518.         ADDR    DI,ARG2
  519.         COMP_STRINGS                    ;COMPARE ARG1 AND ARG2
  520.         JNE     NOTIDENT                ;IF NOT IDENTICAL
  521.         ERROR   17                      ;ARG1 = ARG2, BAD NEWS
  522.         STC
  523.         RET
  524. NOTIDENT:
  525.         ADDR    CX,SSPATH
  526.         ADDR    DX,SPREFIX
  527.         PUSH    BX
  528.         ADD     BX,OFFSET ARG1
  529.         CALL    FIXPATH                 ;PARSE SOURCE PATHNAME
  530.         POP     BX
  531.         CMP     AX,TYPE_UNK
  532.         JNE     GOODPATH                ;IF APPARENTLY OK
  533.         ADDR    DX,ARG1
  534.         CALL    ERRORMSG
  535.         ERROR   2                       ;NONEXISTENT PATHNAME, COMPLAIN
  536.         STC
  537.         RET
  538. GOODPATH:
  539.         MOV     WORD PTR [BX].SRCTYPE,AX     ;SAVE TYPE OF SOURCE
  540.     CMP    AX,TYPE_DIR             ;IS IT A DIRECTORY?
  541.     JNE    RSET                 ;NO.
  542.     CMP    BYTE PTR DS:RFLAG,TRUE         ;R FLAG SET?
  543.     JE    RSET            ;IF OK
  544.     ADDR    DX,ARG1            ;SHOW NAME
  545.     CALL    ERRORMSG
  546.     ERROR    7            ;COMPLAIN ABOUT DIRECTORY
  547.     STC                ;SIGNAL ERROR
  548.     RET
  549. RSET:
  550.         ADDR    SI,ARG2
  551. PDEST:  PUSH    SI
  552. SRCBS:  MOV     AX,[SI]                 ;FIND END OF DEST
  553.         COMPLIST <0,SPACE,TAB>,GOTEND
  554.         INC     SI
  555.         JMP     SRCBS
  556. GOTEND:
  557.         DEC     SI
  558.         CMP     [SI],BYTE PTR '\'       ;DOES DEST SPEC END W. BACKSLASH?
  559.         JNE     NOBS                    ;NO, IT DOESN'T
  560.         MOV     [SI],BYTE PTR 0         ;IF SO, REMOVE IT
  561. NOBS:   COPYPATH ARG2,ARG2A             ;MAKE ARG2A = ARG2
  562.         POP     SI                      ;POINT TO START OF ARG2 AGAIN
  563.         ADDR    CX,DSPATH
  564.         ADDR    DX,DPREFIX
  565.         PUSH    BX
  566.         MOV     BX,SI
  567.         CALL    FIXPATH                 ;PARSE DEST PATHNAME
  568.         POP     BX
  569.         MOV     WORD PTR [BX].DESTTYPE,AX       ;SAVE DEST TYPE
  570.         CMP     AL,TYPE_AFN
  571.         JE      BADDEST                 ;DEST CAN'T BE AFN
  572.         CMP     AL,TYPE_UFN
  573.         JNE     NOTUFN                  ;IF DEST TYPE IS UFN,
  574.         CMP     WORD PTR DS:NUMARGS,2   ;BETTER HAVE ONLY 1 SOURCE
  575.         JG      BADDEST
  576.         CMP     WORD PTR DS:SRCTYPE,TYPE_AFN  ;AND SOURCE TYPE BETTER NOT BE AFN
  577.         JNE     NOTUFN
  578. BADDEST:
  579.         ERROR   3
  580.         STC
  581.         RET
  582. NOTUFN:
  583.         COMPLIST <TYPE_DSP,TYPE_DRV,TYPE_DIR>,DESTDSP ;IF DEST IS DIR OR DRIVE
  584.         CMP     AL,TYPE_UNK
  585.         JNE     SHORT DESTOK            ;IF DEST EXISTS
  586. DESTNX:
  587.         MOV     AX,WORD PTR [BX].SRCTYPE  ;DEST DOESN'T EXIST, SO IF
  588.         CMP     AL,TYPE_DIR             ;SOURCE TYPE IS DIRECTORY,
  589.         JNE     DESTOK
  590.         CALL    SETUP_DEST_DIR          ;MAKE DEST A DIRECTORY, TOO
  591.         JMP     SHORT DESTOK
  592. DESTDSP: MOV    AX,WORD PTR [BX].SRCTYPE  ;DEST IS DIRECTORY, DIR SPEC OR DRIVE
  593.         CMP     AL,TYPE_DIR             ;IS SOURCE A DIRECTORY? -
  594.         JNE     DESTOK                  ;- NO
  595.         CALL    SETUP_SRC_DIR           ;- YES, SOURCE IS DIRECTORY, SET IT UP
  596.         JB      ERRRET                  ;IF ERROR
  597.         MOV     AX,WORD PTR [BX].DESTTYPE
  598.         CMP     AX,TYPE_DIR             ;IS DEST A DIRECTORY? -
  599.         JNE     DESTOK                  ;- NO
  600.         CALL    SETUP_DEST_DIR          ;- YES, SET IT UP, TOO
  601. ;*******************************
  602. ; CHECK FOR INCOMPATIBLE TYPES *
  603. ;*******************************
  604. DESTOK:
  605.         MOV     CX,WORD PTR [BX].DESTTYPE    ;GET DEST TYPE
  606.         MOV     AX,WORD PTR [BX].SRCTYPE     ;GET SOURCE TYPE
  607.         CMP     AX,TYPE_DIR             ;IS SOURCE A DIRECTORY? -
  608.         JNE     TYPEOK                  ;- NO, IT ISN'T
  609.         CMP     CX,TYPE_DIR             ;- YES, SOURCE IS DIRECTORY,
  610.         JE      TYPEOK                  ;DEST BETTER BE DIRECTORY
  611.         CMP     CX,TYPE_DRV             ;OR DRIVE SPEC
  612.         JE      TYPEOK
  613.         ERROR   3                       ;ELSE INCOMPATIBLE TYPE ERROR
  614. ERRRET: STC                             ;ERROR RETURN
  615.         RET
  616. TYPEOK: CLC                             ;NORMAL RETURN
  617.         RET
  618. SETUP   ENDP
  619.  
  620. ;**********************************************
  621. ; MOVE IS FROM DIR TO DIR, DIR SPEC OR DRIVE
  622. ; BUILD FULL DEST PATHNAME (IN ARG2A) AND CHECK
  623. ; ITS TYPE.  (SETS CARRY ON ERROR)
  624. ;
  625. SETUP_SRC_DIR PROC NEAR
  626.         COPYPATH ARG2,DSPATH            ;COPY DEST DIRECTORY OR DRIVE SPEC TO
  627.                                         ;DEST PATH (USE AS SCRATCH AREA)
  628.         DEC     DI                      ;BACK UP OVER NULL
  629.         MOV     AX,WORD PTR [BX].DESTTYPE
  630.         CMP     AX,TYPE_DIR             ;SEE IF DEST IS DIRECTORY
  631.         JNE     NOTDIR                  ;NOPE
  632.         MOV     BYTE PTR [DI],'\'       ;YES, ADD BACKSLASH TO DEST NAME
  633.         INC     DI
  634.         DEC     CX
  635. NOTDIR: ADDR    SI,ARG1                 ;POINT TO SOURCE DIRECTORY NAME
  636.         CMP     BYTE PTR [SI+1],':'     ;DRIVE SPECIFIED? -
  637.         JNE     NODRV                   ;- NO IT WASN'T
  638.         ADD     SI,2                    ;- YES, IT WAS, SKIP IT
  639. NODRV:
  640.         CALL    CPYCNT                  ;COPY SOURCE DIRECTORY NAME (MINUS
  641.                                         ;DRIVE SPEC) TO DEST PATH
  642.         COPYPATH DSPATH,ARG2A           ;COPY AUGMENTED DEST PATH TO ARG2A
  643.         ADDR    CX,DSPATH
  644.         ADDR    DX,DPREFIX
  645.         PUSH    BX
  646.         ADD     BX,OFFSET ARG2A
  647.         CALL    FIXPATH                 ;PARSE FULL DEST PATHNAME
  648.         POP     BX
  649.         MOV     WORD PTR [BX].DESTTYPE,AX    ;SAVE DEST TYPE
  650.         CMP     AL,TYPE_UNK
  651.         JNE     DESTXST                 ;IF DEST EXISTS
  652.         MOV     AX,WORD PTR [BX].SRCTYPE  ;DEST DOESN'T EXIST, GET SOURCE TYPE
  653.         CMP     AX,TYPE_DIR             ;IF SOURCE IS A DIRECTORY,
  654.         JNE     DESTXST
  655.         MOV     [BX].DESTTYPE,TYPE_DIR  ;MAKE DEST A DIRECTORY, TOO
  656. DESTXST:
  657.         CLC
  658.         RET
  659. SETUP_SRC_DIR ENDP
  660.  
  661. ;***************************************************************
  662. ; THIS PROCEDURE IS CALLED IF THE DESTINATION IS A NEW DIRECTORY
  663. ;
  664. SETUP_DEST_DIR PROC NEAR
  665.         ADDR    SI,DSPATH
  666.         ADDR    DI,DPREFIX
  667.         PUSH    DI
  668.         MOV     CX,PATHSIZE
  669.         CALL    CPYCNT                  ;COPY SEARCH PATH TO PREFIX
  670.         POP     DI
  671.         MOV     CX,PATHSIZE
  672.         MOV     AL,0
  673.         REPNE   SCASB                   ;FIND END OF DEST PREFIX
  674.         DEC     DI
  675.         MOV     [DI],BYTE PTR '\'       ;ADD BACKSLASH
  676.         MOV     [DI+1],BYTE PTR 0
  677.         MOV     [BX].NEWDIR,WORD PTR 1  ;SET "NEW DIRECTORY FLAG"
  678.         MOV     WORD PTR [BX].DESTTYPE,TYPE_DIR ;SET DEST TYPE = DIRECTORY
  679.         RET
  680. SETUP_DEST_DIR ENDP
  681.  
  682.         PAGE +
  683. ;****************************************************************************
  684. ; THIS ROUTINE TAKES THE INFO ON A FILE IN THE DTA AND USES IT TO GENERATE
  685. ; FULL, UNAMBIGUOUS SOURCE AND DESTINATION FILE NAMES BY ADDING THE NECESSARY
  686. ; DIRECTORY PREFIXES TO IT.  IT SETS THE CARRY FLAG IF THE "FILE"
  687. ; IS "." OR "..", OR IF THE SOURCE IS IDENTICAL TO THE DESTINATION.
  688. ;
  689. BUILD_NAMES  PROC  NEAR
  690.         COPYPATH SPREFIX,SRCNAME        ;GET SOURCE PREFIX, COPY TO SOURCE NAME
  691.         DEC     DI                      ;BACK UP OVER NULL
  692.         ADDR    SI,(DTA+30)             ;POINT TO FILE NAME WE FOUND
  693.         CMP     [SI],BYTE PTR '.'       ;DOES IT START WITH .? -
  694.         JNE     NOTDOT                  ;- NO
  695.         STC                             ;- YES, SET CARRY TO SKIP IT
  696.         RET
  697. NOTDOT:
  698.         CALL    CPYCNT                  ;ADD IT TO SOURCE PREFIX
  699.         CMP     WORD PTR [BX].DESTTYPE,TYPE_UFN  ;IS DEST A UFN?
  700.         JE      DESTUFN                 ;YES, JUST USE IT
  701.         CMP     WORD PTR [BX].DESTTYPE,TYPE_UNK
  702.         JE      DESTUFN                 ;DITTO IF DEST DOESN'T EXIST
  703.                                         ;IF NOT, MAKE DEST NAME = SOURCE NAME
  704.         COPYPATH DPREFIX,DESTNAME       ;COPY DEST PREFIX TO DEST NAME
  705.         DEC     DI                      ;BACK UP OVER NULL
  706.         ADDR    SI,DTA+30               ;POINT TO FILE NAME WE FOUND
  707.         CALL    CPYCNT                  ;ADD IT TO DEST PREFIX
  708.         JMP     SHORT DONE              ;GO TO NEXT STEP
  709. DESTUFN:                                ;DEST IS A FILE, NOT A DIRECTORY
  710.         COPYPATH ARG2,DESTNAME          ;SO DESTNAME JUST = ARG2
  711. DONE:
  712.         CALL    CHECK_NAMES             ;CHECK SOURCE AND DEST FOR IDENTITY
  713.         RET
  714. BUILD_NAMES ENDP
  715.  
  716.         PAGE +
  717. ;*********************************************************************
  718. ; THIS PROCEDURE CHECKS THE SOURCE AND DEST FILES, AND SETS THE CARRY
  719. ; FLAG IF THEY ARE IDENTICAL
  720. ;
  721. CHECK_NAMES PROC NEAR
  722.         MOV     BX,WORD PTR DS:RBASE    ;GET ADDR. OF DATA STRUCTURE
  723.         MOV     AH,SET_DTA
  724.         MOV     DX,OFFSET DEST_DTA
  725.         INT     DOS                     ;SET DTA
  726.         ADDR    DX,ARG2                 ;POINT TO DESTINATION
  727.         MOV     CX,0FFH
  728.         MOV     AH,FIND_FIRST
  729.         INT     DOS                     ;SEARCH FOR IT
  730.         PUSHF
  731.         ADDR    DX,DTA
  732.         MOV     AH,SET_DTA
  733.         INT     DOS                     ;RESET DTA
  734.         POPF
  735.         JNB     GOTDEST                 ;IF FOUND IT
  736.         CLC                             ;OK IF IT DOESN'T EXIST
  737.         RET
  738. GOTDEST: ADDR   SI,DTA+21               ;POINT TO INFO ON SOURCE
  739.         MOV     DI,OFFSET DEST_DTA+21   ;POINT TO INFO ON DEST
  740.         MOV     CX,9                    ;SIZE OF FILE ATTRIBUTES
  741.         REPE    CMPSB                   ;COMPARE SOURCE AND DEST
  742.         JNE     NOTEQU                  ;IF NOT =
  743.         COMP_STRINGS                    ;COMPARE STRINGS
  744.         JNE     NOTEQU                  ;IF SOURCE AND DEST NAMES NOT EQUAL
  745.         STC                             ;FILES ARE EQUAL (NAMES AND ATTRIB.)
  746.         RET
  747. NOTEQU: CLC
  748.         RET
  749. CHECK_NAMES ENDP
  750.         PAGE +
  751. ;**************************************************************************
  752. ; THIS ROUTINE COPIES A SINGLE FILE (SRCNAME) TO ITS DESTINATION (DESTNAME)
  753. ; ON ANOTHER DISK.
  754. ;
  755. COPY_FILE PROC  NEAR
  756.         ADDR    DX,SRCNAME              ;DX = SOURCE FILE NAME
  757.         MOV     AL,READ_ACCESS
  758.         MOV     AH,DOS2_OPEN
  759.         INT     DOS                     ;TRY TO OPEN SOURCE FILE
  760.         JC      FAIL                    ;IF CAN'T
  761.         MOV     WORD PTR DS:INHANDLE,AX    ;SAVE FILE HANDLE
  762.         CALL    GETOK                   ;GET CONFIRMATION IF DEST EXISTS
  763.         JNC     OKGIVEN                 ;IF OK TO DELETE
  764.         MOV     BX,WORD PTR DS:INHANDLE ;IF NOT OK, GET FILE HANDLE
  765.         MOV     AH,DOS2_CLOSE
  766.         INT     DOS                     ;CLOSE INPUT FILE
  767.         RET                             ;EXIT W/O MOVING
  768. FAIL:   ADDR    DX,SRCNAME              ;POINT TO SOURCE FILE NAME
  769.         CALL    ERRORMSG                ;SHOW IT
  770.         ERROR   5                       ;COMPLAIN THAT CAN'T OPEN
  771.         JMP     EXIT2                   ;EXIT 2 DOS
  772. OKGIVEN: ADDR   DX,DESTNAME
  773.         MOV     CL,BYTE PTR [BX].DTA+21  ;MAKE DEST ATTRIBUTES=SOURCE ATTRIB.
  774.         MOV     CH,0
  775.         MOV     AH,DOS2_CREATE
  776.         INT     DOS                     ;CREATE FILE (OR TRUNCATE OLD ONE)
  777.         JNC     CREATED                 ;IF OK
  778.         ADDR    DX,DESTNAME
  779.         CALL    ERRORMSG                ;CREATE FAILED, SHOW FILE NAME
  780.         ERROR   5                       ;COMPLAIN THAT CAN'T OPEN
  781.         JMP     CLOSE1
  782. CREATED:
  783.         MOV     WORD PTR DS:OUTHANDLE,AX   ;SAVE OUTPUT HANDLE
  784. COPYLOOP:
  785.         PUSH    BX
  786.         MOV     BX,WORD PTR DS:INHANDLE ;BX = FILE HANDLE
  787.         MOV     DX,OFFSET BUFFER        ;DX = BUFFER OFFSET
  788.         MOV     CX,BUFSIZE              ;CX = BUFFER SIZE
  789.         MOV     AH,READ                 ;USING DOS 2 CALL,
  790.         INT     DOS                     ;READ FROM SOURCE
  791.         POP     BX
  792.         JC      RDERR                   ;IF ERROR
  793.         MOV     CX,AX                   ;SAVE AMT. READ
  794.         CMP     AX,0
  795.         JE      ENDCOPY                 ;IF 0
  796.         PUSH    BX
  797.         MOV     BX,WORD PTR DS:OUTHANDLE ;BX = FILE HANDLE
  798.         MOV     DX,OFFSET BUFFER        ;DX = BUFFER OFFSET
  799.         MOV     AH,WRITE
  800.         INT     DOS                     ;WRITE BUFFER TO DEST
  801.         POP     BX
  802.         JC      WRERR                   ;IF ERROR
  803.         CMP     AX,CX                   ;WERE ALL BYTES WRITTEN?
  804.         JE      COPYLOOP                ;YES, KEEP GOING
  805.     ADDR    DX,DESTNAME        ;POINT TO DEST NAME
  806.     CALL    ERRORMSG        ;SHOW IT
  807.         ERROR   10                      ;PROBABLY DISK FULL
  808.         JMP     SCRATCH            ;ABORT
  809. WRERR:  ADDR    DX,DESTNAME        ;POINT TO DEST NAME
  810.     CALL    ERRORMSG        ;SHOW IT
  811.     ERROR   8                       ;WRITE ERROR
  812.         JMP     SCRATCH                 ;ABORT
  813. RDERR:  ADDR    DX,SRCNAME        ;POINT TO SOURCE NAME
  814.     CALL    ERRORMSG        ;SHOW IT
  815.     ERROR   9                       ;READ ERROR
  816.         JMP     SCRATCH                 ;ABORT
  817. ENDCOPY: PUSH   BX                      ;NO ERRORS
  818.         MOV     BX,WORD PTR DS:INHANDLE    ;GET INPUT FILE HANDLE
  819.         MOV     AH,FILE_TIMES
  820.         MOV     AL,0                    ;GET DATE AND TIME
  821.         INT     DOS                     ;GET IT
  822.         MOV     BX,WORD PTR DS:OUTHANDLE   ;GET OUTPUT FILE HANDLE
  823.         MOV     AH,FILE_TIMES
  824.         MOV     AL,1
  825.         INT     DOS                     ;SET OUTPUT DATE AND TIME SAME AS INPUT
  826.         MOV     BX,WORD PTR DS:INHANDLE
  827.         MOV     AH,DOS2_CLOSE
  828.         INT     DOS                     ;CLOSE INPUT FILE
  829.         MOV     BX,WORD PTR DS:OUTHANDLE
  830.         MOV     AH,DOS2_CLOSE
  831.         INT     DOS                     ;CLOSE OUTPUT FILE
  832.         POP     BX
  833.         ADDR    DX,SRCNAME              ;POINT TO SOURCE NAME
  834.     CALL    UNLINK2            ;REMOVE IT
  835.         JB      DELERR                  ;IF SOME PROBLEM
  836.         RET                             ;ALL DONE
  837. DELERR: ADDR    DX,SRCNAME              ;CAN'T DELETE FILE, SHOW FILE NAME
  838.         CALL    ERRORMSG
  839.         ERROR   13                      ;AND ERROR MSG.
  840.         RET
  841.  
  842. SCRATCH:
  843.     PUSH    BX
  844.     MOV    BX,WORD PTR OUTHANDLE
  845.     MOV    AH,DOS2_CLOSE
  846.     INT    DOS            ;CLOSE OUTPUT FILE
  847.     POP    BX
  848.     ADDR    DX,DESTNAME
  849.     CALL    UNLINK2            ;REMOVE PARTIAL FILE
  850.     JMP    CLOSE1            ;CLOSE INPUT AND EXIT
  851.  
  852. COPY_FILE ENDP
  853.  
  854. PAGE +
  855. ;*******************************************************************
  856. ; THIS ROUTINE "MOVES" A FILE (SRCNAME) BY RENAMING IT (TO DESTNAME)
  857. ;
  858. RENAME_FILE PROC NEAR
  859.         CALL    GETOK                   ;SEE IF FILE EXISTS
  860.         JNC     OK                      ;USER SAID OK TO ERASE
  861.         RET                             ;NOT OK, SKIP THIS ONE
  862. OK:     ADDR    DX,SRCNAME              ;POINT TO SOURCE
  863.         ADDR    DI,DESTNAME             ;AND DEST
  864.         MOV     AH,DOS2_RENAME
  865.         PUSH    BX
  866.         INT     DOS                     ;RENAME
  867.         POP     BX
  868.         JNC     RENOK                   ;IF OK
  869.         ADDR    DX,SRCNAME
  870.         CALL    ERRORMSG                ;SHOW SOURCE
  871.         ERROR   11                      ;SHOULDN'T HAPPEN
  872.         JMP     EXIT2
  873. RENOK:  RET
  874. RENAME_FILE ENDP
  875.  
  876.         PAGE +
  877. ;*******************************************************************
  878. ;       THIS ROUTINE CHECKS TO SEE IF THE DEST FILE EXISTS.
  879. ;       IF IT DOES, AND IF THE CONFIRM FLAG IS SET, IT ASKS
  880. ;       FOR CONFIRMATION BEFORE DELETING THE FILE.  IF THE
  881. ;       CONFIRM FLAG IS NOT SET, IT JUST DELETES IT.
  882. ;       ON EXIT, 'C'=1 IF THE USER REPLIED 'N' TO THE CONFIRM MSG.
  883. ;
  884. GETOK   PROC    NEAR
  885.         ADDR    DX,DESTNAME
  886.         MOV     AL,0
  887.         MOV     AH,CHMOD
  888.         INT     DOS                     ;GET ATTRIBUTES FOR DEST
  889.         JNC     EXISTS                  ;IF FILE EXISTS
  890.         CLC
  891.         RET
  892. EXISTS:
  893.         CMP     BYTE PTR DS:IFLAG,TRUE  ;IS FLAG SET TO CONFIRM?
  894.         JNE     COK                     ;NO.
  895.         ADDR    DX,DESTNAME
  896.         CALL    ERRORMSG                ;SHOW DEST FILE
  897.         ERROR   4                       ;ASK FOR CONFIRMATION
  898.     CALL    GETYORN            ;GET Y OR N RESPONSE
  899.         CMP     AL,'Y'                  ;IS IT YES?
  900.         JNE     ABEXIT                  ;NO, SIGNAL CALLING ROUTINE
  901. COK:
  902. TRYAGAIN:
  903.         ADDR    DX,DESTNAME
  904.         MOV     AH,UNLINK
  905.         INT     DOS                     ;DELETE THE FILE
  906.         JNC     OKEXIT                  ;IF NO PROBLEM
  907.         CMP     AX,5                    ;WAS FILE R/O? (THIS OUGHT TO BE
  908.                                         ; THE ONLY POSSIBLE ERROR)
  909.         JNE     OKEXIT                  ;EXIT IF SOME OTHER ERROR
  910.     ADDR    DX,DESTNAME
  911.     CALL    ERRORMSG        ;SHOW DEST FILE NAME
  912.         ERROR   6                       ;R/O FILE, QUERY USER AGAIN
  913.     CALL    GETYORN            ;GET Y OR N RESPONSE
  914.         CMP     AL,'Y'                  ;TEST FOR 'Y' RESPONSE
  915.         JNE     ABEXIT                  ;ABORT IF USER SAYS 'N'
  916.         MOV     CX,0                    ;'Y' TYPED CLEAR ALL ATTRIBUTES
  917.         ADDR    DX,DESTNAME             ;POINT TO FILE NAME
  918.         MOV     AH,CHMOD
  919.         MOV     AL,1                    ;CHANGE ATTRIBUTES
  920.         INT     DOS                     ;TRY MAKING IT R/W
  921.         JMP     TRYAGAIN                ;TRY TO ERASE IT AGAIN
  922. ABEXIT: STC
  923.         RET
  924. OKEXIT: CLC
  925.         RET
  926. GETOK   ENDP
  927.  
  928. ; PRTERR = PRINT ERROR MESSAGE (DX POINTS TO OFFSET FROM DGROUP)
  929.  
  930. PRTERR: PUSH    DS
  931.         MOV     AX,DGROUP
  932.         MOV     DS,AX
  933.         CALL    ERRORMSG
  934.         POP     DS
  935.     RET
  936.  
  937. CLOSE2:  MOV    BX,WORD PTR OUTHANDLE
  938.         MOV     AH,DOS2_CLOSE
  939.         INT     DOS                     ;CLOSE OUTPUT FILE
  940. CLOSE1:
  941.         MOV     BX,WORD PTR INHANDLE
  942.         MOV     AH,DOS2_CLOSE
  943.         INT     DOS                     ;CLOSE INPUT FILE
  944. EXIT2:
  945.         MOV     AH,EXIT
  946.         INT     DOS                     ;EXIT TO DOS
  947.  
  948. CODE    ENDS
  949.         END     ENTRY
  950.  
  951.  
  952.